﻿using Libs;
using System;
using System.IO;
using System.Windows.Forms;
using WriteForFighting.FightingAPI;
using WriteForFighting.Game.Asset;
using WriteForFighting.Game.Entity;
using WriteForFighting.Game.View.Control;

namespace WriteForFighting.Game.View
{
    sealed class ViewGameMain : ViewBase
    {
        private const double PlayerDefaultY = 300.0d;
        private const double Player1DefaultX = 100.0d;
        private const double Player2DefaultX = 500.0d;

        private static int colorString = DX.GetColor(0, 0, 0);
        private static int colorStringEdge = DX.GetColor(255, 255, 255);
        private static int colorUIBack = DX.GetColor(150, 150, 150);
        private static int colorUIPartition = DX.GetColor(200, 200, 200);

        private EntityManager entityPlayersManager = new EntityManager(2, false);
        private EntityManager entityBulletsManager = new EntityManager(128, true);
        private EntityManager entityEffectsManager = new EntityManager(128, true);
        private ControlManager controlManager = new ControlManager(20);
        private bool isRunningGame;

        private GraphicButton player1AddButton = new GraphicButton(610, 113, Drawable.IconOpen);
        private TextLabel player1NameText = new TextLabel(610, 5, "機体1", colorString, Font.Header5AA, colorStringEdge);
        private TextLabel player1InfoText = new TextLabel(610, 30, "", colorString, Font.NormalInfoAA);
        private GraphicButton player2AddButton = new GraphicButton(610, 233, Drawable.IconOpen);
        private TextLabel player2NameText = new TextLabel(610, 150, "機体2", colorString, Font.Header5AA, colorStringEdge);
        private TextLabel player2InfoText = new TextLabel(610, 175, "", colorString, Font.NormalInfoAA);
        private GraphicButton startButton = new GraphicButton(600, 566, Drawable.IconPlay);
        private GraphicButton stopButton = new GraphicButton(640, 566, Drawable.IconStop);

        public ViewGameMain()
        {
            stopButton.Enabled = false;

            controlManager.AddControl(player1AddButton);
            controlManager.AddControl(player1NameText);
            controlManager.AddControl(player1InfoText);
            controlManager.AddControl(player2AddButton);
            controlManager.AddControl(player2NameText);
            controlManager.AddControl(player2InfoText);
            controlManager.AddControl(startButton);
            controlManager.AddControl(stopButton);

            player1AddButton.OnButtonClicked += OnPlayer1AddButtonClicked;
            player2AddButton.OnButtonClicked += OnPlayer2AddButtonClicked;
            startButton.OnButtonClicked += OnStartButtonClicked;
            stopButton.OnButtonClicked += OnStopButtonClicked;
        }

        public override void Update(int gameTickCount)
        {
            if (isRunningGame)
            {
                entityPlayersManager.UpdateEntities(gameTickCount, entityPlayersManager, entityBulletsManager, entityEffectsManager);
                entityBulletsManager.UpdateEntities(gameTickCount, entityPlayersManager, entityBulletsManager, entityEffectsManager);
                entityEffectsManager.UpdateEntities(gameTickCount, entityPlayersManager, entityBulletsManager, entityEffectsManager);
            }

            controlManager.UpdateControls();
        }

        public override void Draw(int gameTickCount)
        {
            DX.SetDrawMode(DX.DX_DRAWMODE_BILINEAR);
            entityPlayersManager.DrawEntities(gameTickCount);
            entityBulletsManager.DrawEntities(gameTickCount);
            entityEffectsManager.DrawEntities(gameTickCount);
            DX.SetDrawMode(DX.DX_DRAWMODE_NEAREST);

            DX.DrawBox(600, 0, GD.SCREEN_WIDTH, GD.SCREEN_HEIGHT, colorUIBack, DX.TRUE);

            controlManager.DrawControls();
            DX.DrawBox(600, 143, 800, 144, colorUIPartition, DX.FALSE);
        }

        private void OnPlayer1AddButtonClicked()
        {
            LoadPlayer(0);
        }

        private void OnPlayer2AddButtonClicked()
        {
            LoadPlayer(1);
        }

        private void OnStartButtonClicked()
        {
            player1AddButton.Enabled = false;
            player2AddButton.Enabled = false;
            startButton.Enabled = false;
            stopButton.Enabled = true;
            isRunningGame = true;
        }

        private void OnStopButtonClicked()
        {
            player1AddButton.Enabled = true;
            player2AddButton.Enabled = true;
            startButton.Enabled = true;
            stopButton.Enabled = false;
            isRunningGame = false;
            entityBulletsManager.DeleteAll();
            entityEffectsManager.DeleteAll();

            for (int i = 0; i < entityPlayersManager.MaxEntities; ++i)
            {
                EntityPlayer ep = (EntityPlayer)entityPlayersManager.GetEntity(i);

                if (ep != null)
                {
                    double x = 0;
                    switch (ep.PlayerType)
                    {
                        case 0:
                            x = Player1DefaultX;
                            break;

                        case 1:
                            x = Player2DefaultX;
                            break;
                    }

                    entityPlayersManager.OverwriteEntity(new EntityPlayer(x, PlayerDefaultY, 0,
                        ep.PlayerProgramPath,
                        entityBulletsManager, ep.PlayerType), i);
                }
            }
        }

        private void LoadPlayer(int playerID)
        {
            using (OpenFileDialog dialog = new OpenFileDialog())
            {
                dialog.Title = "機体プログラムを開く";
                dialog.Filter = "機体プログラム(*.dll)|*.dll";

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    EntityPlayer entityPlayer = null;

                    try
                    {
                        double x = 0;
                        switch (playerID)
                        {
                            case 0:
                                x = Player1DefaultX;
                                break;

                            case 1:
                                x = Player2DefaultX;
                                break;
                        }

                        entityPlayer = new EntityPlayer(x, PlayerDefaultY, 0, dialog.FileName,
                            entityBulletsManager, playerID);
                        entityPlayersManager.OverwriteEntity(entityPlayer, playerID);
                    }
                    catch (BadImageFormatException e)
                    {
                        Console.WriteLine(e);
                        MessageBox.Show("'" + dialog.FileName + "'は有効な機体プログラムではありません。",
                            GD.APP_NAME,
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Exclamation);
                        return;
                    }
                    catch (IOException e)
                    {
                        Console.WriteLine(e);
                        MessageBox.Show("'" + dialog.FileName + "'の読み込みに失敗しました。",
                            GD.APP_NAME,
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Exclamation);
                        return;
                    }

                    UpdatePlayerInfoView(playerID, entityPlayer.Player);
                }
            }
        }

        private void UpdatePlayerInfoView(int playerID, Player player)
        {
            TextLabel nameTextLabel = null;
            TextLabel infoTextLabel = null;

            switch (playerID)
            {
                case 0:
                    nameTextLabel = player1NameText;
                    infoTextLabel = player1InfoText;
                    break;

                case 1:
                    nameTextLabel = player2NameText;
                    infoTextLabel = player2InfoText;
                    break;
            }

            PlayerProgramAttribute playerInfo = PlayerAssemblyLoader.GetPlayerInfo(player);

            nameTextLabel.Text = playerInfo.Name;
            infoTextLabel.Text = "開発者:" + playerInfo.Author + "\n" +
                                 "バージョン:" + playerInfo.Version;
        }
    }
}
